package com.fun.feifun.base.utils;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.Year;
import java.time.temporal.ChronoUnit;
import java.util.*;

public class DateUtil {

    private static Logger logger = LoggerFactory.getLogger(DateUtil.class);

    private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    private static final String DATE_FORMAT_YMDHMSSS = "yyyy-MM-dd HH:mm:ss.SSS";
    private static final String DATE_FORMAT_YMDHMS = "yyyyMMddHHmmss";
    private static final String DATE_FORMAT_YMDHMSSS_NOOTHER = "yyyyMMddHHmmssSSS";
    private static final String DATE_FORMAT_YMD = "yyyyMMdd";
    public static final String DATE_FORMAT_Y_M_D = "yyyy-MM-dd";

    private static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected synchronized SimpleDateFormat initialValue() {
            return new SimpleDateFormat(DATE_FORMAT);
        }
    };

    public void unload() {
        threadLocal.remove(); // Compliant
    }

    public static String format(Date date) {
        return threadLocal.get().format(date);
    }

    public static Date parse(String textDate) throws ParseException {
        return threadLocal.get().parse(textDate);
    }

    public static String getDateAddDay(Date date, int day) {
        // 一天的毫秒数
        Long oneDay = Long.parseLong((24 * 60 * 60 * 1000) + "");
        Long dateLong = date.getTime() + (day * oneDay);
        return threadLocal.get().format(new Date(dateLong));
    }

    /**
     * 获取某年第一天日期
     *
     * @param year 年份
     * @return Date
     */
    public static String getYearFirst(int year, String format) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(calendar.getTime());
    }

    /**
     * 日期转字符串，格式为yyyy-MM-dd HH:mm:ss
     *
     * @param date
     * @return
     */
    public static String getYMdHMDString(String date) {
        if (Objects.isNull(date)) {
            return null;
        }
        try {
            SimpleDateFormat destsmf = new SimpleDateFormat(DATE_FORMAT);
            Date parse = destsmf.parse(date);
            return destsmf.format(parse);
        } catch (Exception e) {
            logger.error("格式化日期出错，date=" + date, e);
            return null;
        }
    }

    /**
     * 转换字符串格式为其他字符串
     *
     * @param dateStr
     * @return
     */
    public static String getYMdHMToYMdHMsSSS(String dateStr) {
        if (StringUtils.isBlank(dateStr)) {
            return null;
        }
        try {
            SimpleDateFormat destsmf = new SimpleDateFormat(DATE_FORMAT_YMDHMSSS);
            Date formatDate = destsmf.parse(dateStr);
            SimpleDateFormat destsmf2 = new SimpleDateFormat(DATE_FORMAT_YMDHMSSS_NOOTHER);
            return destsmf2.format(formatDate);
        } catch (Exception e) {
            logger.error("格式化日期出错，date=" + dateStr, e);
            return null;
        }
    }

    /**
     * 获取n分钟前：n正数代表将来的日期，负数代表过去
     *
     * @param minute
     * @return
     */
    public static long getBeforeMinute(long time, int minute) {
        try {
            SimpleDateFormat sdate = new SimpleDateFormat(DATE_FORMAT_YMDHMS);
            Date parse = sdate.parse(String.valueOf(time));
            Calendar nowTime = Calendar.getInstance();
            nowTime.setTime(parse);
            nowTime.add(Calendar.MINUTE, minute);
            String format = sdate.format(nowTime.getTime());
            return Long.parseLong(format);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return time;
        }
    }

    /**
     * 获取某年最后一天日期
     *
     * @param year 年份
     * @return Date
     */
    public static String getYearLast(int year, String format) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.roll(Calendar.DAY_OF_YEAR, -1);
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(calendar.getTime());
    }

    /**
     * 获取N天前：n正数代表将来的日期，负数代表过去
     *
     * @param day
     * @return
     */
    public static Date getSomeDay(int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DATE, day);
        return calendar.getTime();
    }

    /**
     * 获取年月日
     *
     * @param date
     * @return
     */
    public static String getYyyyMMdd(Date date) {
        if (null == date) {
            return null;
        }
        try {
            SimpleDateFormat destsmf = new SimpleDateFormat(DATE_FORMAT_Y_M_D);
            return destsmf.format(date);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 获取年月日yyyyMMdd
     *
     * @param date
     * @return
     */
    public static String getYyyyMMdd(String date) {

        if (null == date) {
            return null;
        }
        try {
            SimpleDateFormat sdate = new SimpleDateFormat(DATE_FORMAT_Y_M_D);
            Date parse = sdate.parse(date);
            SimpleDateFormat destsmf = new SimpleDateFormat(DATE_FORMAT_YMD);
            return destsmf.format(parse);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 获取年月日加上时分秒
     *
     * @param date
     * @return
     */
    public static String getStringYMDHMS(String date) {
        if (null == date) {
            return null;
        }
        try {
            SimpleDateFormat sdate = new SimpleDateFormat(DATE_FORMAT_Y_M_D);
            Date parse = sdate.parse(date);
            SimpleDateFormat destsmf = new SimpleDateFormat(DATE_FORMAT);
            return destsmf.format(parse);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 获取某月最后一天日期
     *
     * @param year 年份
     * @return Date
     */
    public static String getMonthLast(String month, String format) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, Integer.parseInt(month.substring(0, 4)));
        calendar.set(Calendar.MONTH, Integer.parseInt(month.substring(5)) - 1);
        int lastDay = calendar.getActualMaximum(Calendar.DATE);
        calendar.set(Calendar.DAY_OF_MONTH, lastDay);
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(calendar.getTime());
    }

    public static List<String> getMonth(String month) {
        List<String> dayList = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_YMD);
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, Integer.parseInt(month.substring(0, 4)));
        calendar.set(Calendar.MONTH, Integer.parseInt("0".equals(month.substring(4, 5)) ? month.substring(5) : month.substring(4)) - 1);
        int lastDay = calendar.getActualMaximum(Calendar.DATE);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        dayList.add(sdf.format(calendar.getTime()));
        for (int i = 0; i < lastDay; i++) {
            calendar.add(Calendar.DAY_OF_MONTH, +1);
            dayList.add(sdf.format(calendar.getTime()));
        }
        return dayList;
    }

    /***
     * 获得昨天日期
     *
     * @return
     */
    public static String getYesterday(String format) {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.DATE, -1);
        SimpleDateFormat startSdf = new SimpleDateFormat(format);
        return startSdf.format(c.getTime());
    }

    public static Integer getYear() {
        return Calendar.getInstance().get(Calendar.YEAR);
    }

    public static String getMonth() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
        return sdf.format(new Date());
    }

    /**
     * 获得当前时间
     *
     * @return
     */
    public static String getNowDate(String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(new Date());
    }

    public static List<String> get365Day(int year) {
        List<String> dayList = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_YMD);
        int m = 1;// 月份计数
        while (m < 13) {
            int month = m;
            Calendar cal = Calendar.getInstance();// 获得当前日期对象
            cal.clear();// 清除信息
            cal.set(Calendar.YEAR, year);
            cal.set(Calendar.MONTH, month - 1);// 1月从0开始
            cal.set(Calendar.DAY_OF_MONTH, 1);// 设置为1号,当前日期既为本月第一天
            dayList.add(sdf.format(cal.getTime()));
            int count = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
            for (int j = 0; j <= (count - 2); j++) {
                cal.add(Calendar.DAY_OF_MONTH, +1);
                dayList.add(sdf.format(cal.getTime()));
            }
            m++;
        }
        return dayList;
    }

    public static List<String> getDays(String monthString) {
        List<String> dayList = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_YMD);
        int month = Integer.parseInt(monthString.substring(5));
        Calendar cal = Calendar.getInstance();// 获得当前日期对象
        cal.clear();// 清除信息
        cal.set(Calendar.YEAR, Integer.parseInt(monthString.substring(0, 4)));
        cal.set(Calendar.MONTH, month - 1);// 1月从0开始
        cal.set(Calendar.DAY_OF_MONTH, 1);// 设置为1号,当前日期既为本月第一天
        dayList.add(sdf.format(cal.getTime()));
        int count = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
        for (int j = 0; j <= (count - 2); j++) {
            cal.add(Calendar.DAY_OF_MONTH, +1);
            dayList.add(sdf.format(cal.getTime()));
        }
        return dayList;
    }

    /**
     * 格式时间
     *
     * @return
     */
    public static String formatNow(String format) {
        return formatDate(new Date(), format);
    }

    public static String getPrevDate(String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        // 判断是否是周末
        if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            calendar.roll(Calendar.DAY_OF_YEAR, -2);
        } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
            calendar.roll(Calendar.DAY_OF_YEAR, -3);
        } else {
            calendar.roll(Calendar.DAY_OF_YEAR, -1);
        }
        Date prevDay = calendar.getTime();
        return sdf.format(prevDay);
    }

    public static String formatDate(Date date, String format) {
        return new SimpleDateFormat(format).format(date);
    }

    /**
     * 把字符串格式转换成日期格式，默认时间格式为yyyy-mm-dd
     *
     * @param strDate
     * @return
     */
    public static Date stringToDate(String strDate, String format) {
        if (format == null || format.length() == 0) {
            format = DATE_FORMAT_Y_M_D;
        }
        DateFormat dateFormat = new SimpleDateFormat(format);
        Date date = null;
        try {
            date = dateFormat.parse(strDate);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return date;

    }

    /**
     * 将日期转换为指定格式的字符串
     *
     * @param date
     * @param format
     * @return
     */
    public static String DateToString(Date date, String format) {
        if (format == null || format.length() == 0) {
            format = DATE_FORMAT_Y_M_D;
        }
        DateFormat dateFormat = new SimpleDateFormat(format);
        return dateFormat.format(date);
    }

    public static String getBeforeTime(long time, int second) {
        if (String.valueOf(time).length()>14){
            time = Long.parseLong(String.valueOf(time).substring(0, 14));
        }
        SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT_YMDHMS);
        Calendar nowTime = Calendar.getInstance();
        try {
            nowTime.setTime(format.parse(time + ""));
        } catch (ParseException e) {
            logger.error(e.getMessage(), e);
        }
        nowTime.add(Calendar.SECOND, second);
        return format.format(nowTime.getTime());
    }

    public static String getDayAdd(int day) {
        SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT_Y_M_D);
        Calendar nowTime = Calendar.getInstance();
        nowTime.add(Calendar.DATE, day);
        return format.format(nowTime.getTime());
    }

    public static String getStringTime(String time, String timePattern, String stringPattern) throws Exception {
        SimpleDateFormat dateFormat = new SimpleDateFormat(timePattern);
        SimpleDateFormat stringFormat = new SimpleDateFormat(stringPattern);
        try {
            Date parse = dateFormat.parse(time);
            return stringFormat.format(parse);
        } catch (ParseException e) {
            throw new Exception(e);
        }
    }

    /**
     * 日期相隔天数
     *
     * @return
     */
    public static int periodDays(String fromDate) {
        long from = DateUtil.parseDate(fromDate, DATE_FORMAT_YMDHMS).getTime();
        long to = System.currentTimeMillis();
        int days = (int) ((to - from) / (1000 * 60 * 60 * 24));
        return days;
    }


    //获取传入时间与当前时间相隔的天数
    public static long getInterval(String dateStr) throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = simpleDateFormat.parse(dateStr);

        long day = 0;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        if (date != null) {
            String end = sdf.format(date);
            date = sdf.parse(end);
        } else {
            throw new NullPointerException();
        }
        Date nowDate = sdf.parse(sdf.format(new Date()));
        day = (date.getTime() - nowDate.getTime()) / (24 * 60 * 60 * 1000);
        return day >= 0 ? day : -day;
    }

    /**
     * 日期相隔小时
     *
     * @return
     */
    public static long durationHours(String fromDate) {
        long from = DateUtil.parseDate(fromDate, DATE_FORMAT_YMDHMS).getTime();
        long to = System.currentTimeMillis();
        int hours = (int) ((to - from) / (1000 * 60 * 60));
        return hours;

    }

    /**
     * 日期相隔分钟
     *
     * @param startInclusive
     * @param endExclusive
     * @return
     */
    public static long durationMinutes(String fromDate) {
        long from = DateUtil.parseDate(fromDate, DATE_FORMAT_YMDHMS).getTime();
        long to = System.currentTimeMillis();
        int minutes = (int) ((to - from) / (1000 * 60));
        return minutes;
    }

    public static Date parseDate(String dateStr, String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        try {
            return sdf.parse(dateStr);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            logger.error(e.getMessage(), e);
        }
        return new Date();
    }

    /**
     * 获取两个日期之间的所有年份
     *
     * @param startDateStr yyyy-mm-dd
     * @param endDateStr   yyyy-mm-dd
     * @return duanhn
     */
    public static List<Integer> yearBetweenTime(String startDateStr, String endDateStr) {
        List<Integer> result = new ArrayList<>();

        LocalDate startDate = LocalDate.of(Integer.parseInt(startDateStr.split("-")[0]), Integer.parseInt(startDateStr.split("-")[1]), Integer.parseInt(startDateStr.split("-")[2]));
        LocalDate endDate = LocalDate.of(Integer.parseInt(endDateStr.split("-")[0]), Integer.parseInt(endDateStr.split("-")[1]), Integer.parseInt(endDateStr.split("-")[2]));

        Year startyear = Year.from(startDate);
        Year endYear = Year.from(endDate);
        // 包含最后一个时间
        for (long i = 0; i <= ChronoUnit.YEARS.between(startyear, endYear); i++) {
            result.add(Integer.parseInt(startyear.plusYears(i).toString()));
        }
        return result;
    }

}
